-
Notifications
You must be signed in to change notification settings - Fork 102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement scroll up and down #103
base: master
Are you sure you want to change the base?
Conversation
Thanks for the contribution! Could you point me to documentation for these escape sequences? |
They are (sparsely) documented here: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html The most common use of this is when you call |
Any chance this can be merged? I ran into the lack of scroll support when using the Python curses module. Scrolling can be invoked implicitly in ncurses (I believe this is due to hardscroll.c, which appears to detect 'scroll-like' updates, even if a scroll was not explicitly requested.) Here is a script that demonstrates psuedo-scroll behavior. With
I don't know of any easy way to set the term capabilities with greater granularlity than TERM (to disable scrolling but leave support for other features (e.g. color)), so I would prefer to not use I tested this pull request and it solves both my original issue and causes the above test to pass. |
self.buffer[y] = self.buffer[y + lines].copy() | ||
else: | ||
self.buffer[y].clear() | ||
self.dirty = set(lines_to_scroll) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should update the dirty set rather than replace it.
self.dirty = set(lines_to_scroll) | |
self.dirty.update(lines_to_scroll) |
@@ -1043,6 +1048,26 @@ def debug(self, *args, **kwargs): | |||
By default is a noop. | |||
""" | |||
|
|||
def scroll_up(self, lines): | |||
"""Scroll up `lines` lines.""" | |||
lines_to_scroll = range(self.margins.top, self.margins.bottom + 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should handle when margins is None.
lines_to_scroll = range(self.margins.top, self.margins.bottom + 1) | |
margins = self.margins or Margins(0, self.lines - 1) | |
lines_to_scroll = range(margins.top, margins.bottom + 1) |
if y + lines in set(lines_to_scroll): | ||
self.buffer[y] = self.buffer[y + lines].copy() | ||
else: | ||
self.buffer[y].clear() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scrolling is similar to indexing multiple times, is it not? If we follow its example (and it may be more efficient) we can simply move the lines we want to move and pop the lines we want to erase, rather than copying and clearing the dictionaries. We can also improve efficiency by checking the bottom margin rather than creating a set to test for set inclusion.
if y + lines in set(lines_to_scroll): | |
self.buffer[y] = self.buffer[y + lines].copy() | |
else: | |
self.buffer[y].clear() | |
if y + lines <= margins.bottom: | |
self.buffer[y] = self.buffer[y + lines] | |
else: | |
self.buffer.pop(y, None) |
SU = "S" | ||
|
||
#: *Scroll down* | ||
SD = "T" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While the xterm documentation states that 'T' is the correct code for Scroll Down (SD), the xterm code is implemented to handle the incorrect code '^' and treats 'T' as either mouse tracking or SD (depending on the arguments).
I'm not sure how many (or if any) applications still use the incorrect code.
def scroll_up(self, lines): | ||
"""Scroll up `lines` lines.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation states that a scroll with no parameters scrolls 1 line.
def scroll_up(self, lines): | |
"""Scroll up `lines` lines.""" | |
def scroll_up(self, lines=None): | |
"""Scroll up `lines` lines. | |
:param lines: number of lines to scroll up. defaults to 1 if unspecified. | |
""" | |
lines = lines or 1 |
def scroll_down(self, lines): | ||
"""Scroll down `lines` lines.""" | ||
lines_to_scroll = range(self.margins.bottom, self.margins.top - 1, -1) | ||
for y in lines_to_scroll: | ||
if y - lines in set(lines_to_scroll): | ||
self.buffer[y] = self.buffer[y - lines].copy() | ||
else: | ||
self.buffer[y].clear() | ||
self.dirty = set(lines_to_scroll) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to scroll_up, this should also default to 1 line if the argument is unspecified. However, an argument of 0 is used to reset mouse tracking (may be xterm specific). In any case, if we get an argument of 0, we don't want to scroll at all. And if we don't get an argument we do want to scroll exactly 1 line. However, looking at the current implementation of _parser_fsm
, we may be unable to differentiate between receiving no arguments and receiving a 0 as the first argument. Reading vt100.net, they seem to indicate that for their purposes there is no need to distinguish between the value 0 and an unspecified argument (i.e., an explicit 0 still implies the default). Perhaps this is an xterm specific issue in this case.
Any other changes made to scroll_up should be appropriately mirrored here in scroll_down.
f8e191c
to
fa5255a
Compare
6cea8ec
to
259ee02
Compare
This PR implements handling of the SU and SD CSI commands in
pyte.Stream
and the correspondingscroll_up
andscroll_down
methods inpyte.Screen
.